﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Transactions;

using SMA.GENTEv1.Dados;

namespace SMA.GENTEv1
{
    public class ConfiguracaoRegraContrato
    {
        #region Variaveis Membro
        private int _idConfiguracaoRegraContrato;
        private Contrato _contrato;
        private TipoBeneficio _beneficio;
        private DateTime _dtInicio;
        private DateTime _dtFim;
        private Status _status;
        private decimal _valor;
        private TipoValor _tipoValor;
        private string _obrigatorio;
        private string _extensivoDependente;
        private List<Cidade> _localidade;
        private string _descontoFolha;
        private GENTEEntities _context;
        #endregion
        
        #region Parametros
        public int IdConfiguracaoRegraContrato
        {
            get { return _idConfiguracaoRegraContrato; }
            set { _idConfiguracaoRegraContrato = value; }
        }

        public Contrato Contrato
        {
            get { return _contrato; }
            set { _contrato = value; }
        }

        public TipoBeneficio Beneficio
        {
            get { return _beneficio; }
            set { _beneficio = value; }
        }

        public DateTime DtInicio
        {
            get { return _dtInicio; }
            set { _dtInicio = value; }
        }

        public DateTime DtFim
        {
            get { return _dtFim; }
            set { _dtFim = value; }
        }

        public Status Status
        {
            get { return _status; }
            set { _status = value; }
        }

        public decimal Valor
        {
            get { return _valor; }
            set { _valor = value; }
        }

        public TipoValor TipoValor
        {
            get { return _tipoValor; }
            set { _tipoValor = value; }
        }

        public string Obrigatorio
        {
            get { return _obrigatorio; }
            set { _obrigatorio = value; }
        }

        public string ExtensivoDependente
        {
            get { return _extensivoDependente; }
            set { _extensivoDependente = value; }
        }

        public List<Cidade> Localidade
        {
            get { return _localidade; }
            set { _localidade = value; }
        }

        public string DescontoFolha
        {
            get { return _descontoFolha; }
            set { _descontoFolha = value; }
        }
        #endregion

        #region Construtores
        public ConfiguracaoRegraContrato()
        {
            try
            {
                _context = new GENTEEntities();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public ConfiguracaoRegraContrato(int idConfiguracaoRegraContrato, bool carregaDados)
        {
            try
            {
                _context = new GENTEEntities();
                if (!carregaDados)
                    this._idConfiguracaoRegraContrato = idConfiguracaoRegraContrato;
                else
                    Carregar(idConfiguracaoRegraContrato);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public ConfiguracaoRegraContrato(int idConfiguracaoRegraContrato, bool carregaDados, bool carregaLocalidade)
        {
            try
            {
                _context = new GENTEEntities();
                if (!carregaDados)
                    this._idConfiguracaoRegraContrato = idConfiguracaoRegraContrato;
                else
                    Carregar(idConfiguracaoRegraContrato, carregaLocalidade);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #region Métodos Privados

        #region Métodos Gerais
        private void VerificarCadastro()
        {
            try
            {
                if (this._contrato == null)
                    throw new Exception("É necessário informar o contrato dessa configuração!");

                if (this._contrato.IdContrato == 0)
                    throw new Exception("É necessário informar o contrato dessa configuração!");

                if (this._beneficio == null)
                    throw new Exception("É necessário informar o benefício dessa configuração!");

                if (this._beneficio.IdTipoBeneficio == 0)
                    throw new Exception("É necessário informar o benefício dessa configuração!");

                if (this._status == null)
                    throw new Exception("É necessário informar qual a situação da configuração!");

                if (this._status.IdStatus == 0)
                    throw new Exception("É necessário informar qual a situação da configuração!");

                if (this._dtFim < this._dtInicio)
                    throw new Exception("É necessário informar para o campo Data Final do período de Validade uma data maior daquela que se encontra no campo Data Inicial!");

                if (this._tipoValor == null)
                    throw new Exception("É necessário informar o tipo de valor utilizado pela configuração!");

                if (this._tipoValor.IdTipoValor == 0)
                    throw new Exception("É necessário informar o tipo de valor utilizado pela configuração!");

                if (this._valor == 0)
                {
                    switch (this._tipoValor.IdTipoValor)
                    {
                        case (int)TipoValor.Tipo.Porcentagem:
                            throw new Exception("É necessário informar o valor em porcentagem utilizado pela configuração!");
                        case (int)TipoValor.Tipo.Dinheiro:
                            throw new Exception("É necessário informar o valor em dinheiro utilizado pela configuração!");
                        case (int)TipoValor.Tipo.Unidade:
                            throw new Exception("É necessário informar o valor em unidade utilizado pela configuração!");
                    }
                }

                if (this._obrigatorio == string.Empty)
                    throw new Exception("É necessário informar a obrigatoriedade dessa configuração!");

                if (this._extensivoDependente == string.Empty)
                    throw new Exception("É necessário informar se essa configuração é extendida para os dependentes!");
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void EstruturaGradeHistParam(ref DataTable grade)
        {
            try
            {
                DataColumn idConfiguracaoRegraContrato = new DataColumn();
                idConfiguracaoRegraContrato.ColumnName = "IdConfiguracaoRegraContrato";
                idConfiguracaoRegraContrato.DataType = Type.GetType("System.Int32");
                grade.Columns.Add(idConfiguracaoRegraContrato);

                DataColumn dtInicio = new DataColumn();
                dtInicio.ColumnName = "DtInicio";
                dtInicio.DataType = Type.GetType("System.DateTime");
                grade.Columns.Add(dtInicio);
                
                DataColumn dtFim = new DataColumn();
                dtFim.ColumnName = "DtFim";
                dtFim.DataType = Type.GetType("System.DateTime");
                grade.Columns.Add(dtFim);

                DataColumn status = new DataColumn();
                status.ColumnName = "Status";
                status.DataType = Type.GetType("System.String");
                grade.Columns.Add(status);

                DataColumn localidade = new DataColumn();
                localidade.ColumnName = "Localidade";
                localidade.DataType = Type.GetType("System.String");
                grade.Columns.Add(localidade);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #region Métodos de Seleção
        private void Carregar(int idConfiguracaoRegraContrato)
        {
            try
            {
                var consulta = (from config in _context.tab_configuracao_regra_contrato
                                where config.id_configuracao_regra_contrato == idConfiguracaoRegraContrato
                                select new
                                {
                                    config.id_configuracao_regra_contrato,
                                    config.dt_inicio,
                                    config.dt_fim,
                                    config.valor,
                                    config.obrigatorio,
                                    config.extensivo_dependente
                                });

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    this._idConfiguracaoRegraContrato = list.id_configuracao_regra_contrato;
                    this._dtInicio = list.dt_inicio;
                    this._dtFim = list.dt_fim;
                    this._valor = list.valor;
                    this._obrigatorio = list.obrigatorio;
                    this._extensivoDependente = list.extensivo_dependente;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void Carregar(int idConfiguracaoRegraContrato, bool carregaLocalidade)
        {
            try
            {
                var consulta = (from config in _context.tab_configuracao_regra_contrato
                                where config.id_configuracao_regra_contrato == idConfiguracaoRegraContrato
                                select new
                                {
                                    config.id_configuracao_regra_contrato,
                                    config.dt_inicio,
                                    config.dt_fim,
                                    config.valor,
                                    config.obrigatorio,
                                    config.extensivo_dependente
                                });

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    this._idConfiguracaoRegraContrato = list.id_configuracao_regra_contrato;
                    this._dtInicio = list.dt_inicio;
                    this._dtFim = list.dt_fim;
                    this._valor = list.valor;
                    this._obrigatorio = list.obrigatorio;
                    this._extensivoDependente = list.extensivo_dependente;

                    if (carregaLocalidade)
                        this._localidade = SelectLocalidadesConfig(list.id_configuracao_regra_contrato);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private int RetornaIdConfiguracaoRegraContrato()
        {
            try
            {
                int resultado = 0;

                var consulta = (from config in _context.tab_configuracao_regra_contrato
                                orderby config.id_configuracao_regra_contrato descending
                                select new
                                {
                                    config.id_configuracao_regra_contrato
                                }).Take(1);

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    resultado = list.id_configuracao_regra_contrato;
                }

                return resultado;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private List<Cidade> SelectLocalidadesConfig(int idConfiguracaoRegraContrato)
        {
            try
            {
                List<Cidade> listCidade = new List<Cidade>();

                var consulta = (from cidade in _context.tab_configuracao_regra_localidade
                                where cidade.tab_configuracao_regra_contrato.id_configuracao_regra_contrato == idConfiguracaoRegraContrato
                                select new
                                {
                                    cidade.tab_cidade.id_cidade
                                });

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    Cidade cidade = new Cidade(list.id_cidade);

                    listCidade.Add(cidade);
                }

                return listCidade;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #region Métodos de Persistência
        private void DesativarConfiguracaoAnterior(int idConfiguracaoRegraContrato, int idBeneficio)
        {
            try
            {
                var consulta = (from config in _context.tab_configuracao_regra_contrato
                                where config.id_configuracao_regra_contrato < idConfiguracaoRegraContrato
                                && config.tab_tipo_beneficio.id_tipo_beneficio == idBeneficio
                                orderby config.id_configuracao_regra_contrato descending
                                select config).Take(1);

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    tab_configuracao_regra_contrato tabConfiguracaoRegraContrato = (from config in _context.tab_configuracao_regra_contrato
                                                                                    where config.id_configuracao_regra_contrato == list.id_configuracao_regra_contrato
                                                                                    select config).First();

                    tabConfiguracaoRegraContrato.tab_statusReference.EntityKey = new System.Data.EntityKey("GENTEEntities.tab_status", "id_status", 2);

                    _context.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void SalvarLocalidade(int idConfiguracaoRegraContrato)
        {
            try
            {
                for (int i = 0; i < this._localidade.Count; i++)
                {
                    tab_configuracao_regra_localidade tabConfigLocalidade = new tab_configuracao_regra_localidade();
                    tabConfigLocalidade.tab_configuracao_regra_contratoReference.EntityKey = new System.Data.EntityKey("GENTEEntities.tab_configuracao_regra_contrato", "id_configuracao_regra_contrato", idConfiguracaoRegraContrato);
                    tabConfigLocalidade.tab_cidadeReference.EntityKey = new System.Data.EntityKey("GENTEEntities.tab_cidade", "id_cidade", this._localidade[i].IdCidade);

                    _context.AddTotab_configuracao_regra_localidade(tabConfigLocalidade);
                    _context.SaveChanges();
                }

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #endregion
        
        #region Métodos Públicos

        #region Métodos de Seleção
        public List<ConfiguracaoRegraContrato> SelectRegraAtual(int idBeneficio, int idContrato)
        {
            try
            {
                List<ConfiguracaoRegraContrato> listConfigContrato = new List<ConfiguracaoRegraContrato>();

                var consulta = (from config in _context.tab_configuracao_regra_contrato
                                where config.tab_tipo_beneficio.id_tipo_beneficio == idBeneficio
                                && config.tab_contrato.Id_contrato == idContrato
                                orderby config.id_configuracao_regra_contrato descending
                                select new
                                {
                                    config.id_configuracao_regra_contrato,
                                    config.dt_inicio,
                                    config.dt_fim,
                                    config.valor,
                                    config.obrigatorio,
                                    config.extensivo_dependente,
                                    config.desconto_folha
                                }).Take(1);

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    ConfiguracaoRegraContrato configContrato = new ConfiguracaoRegraContrato();
                    configContrato.IdConfiguracaoRegraContrato = list.id_configuracao_regra_contrato;
                    configContrato.DtInicio = list.dt_inicio;
                    configContrato.DtFim = list.dt_fim;
                    configContrato.Valor = list.valor;
                    configContrato.Obrigatorio = list.obrigatorio;
                    configContrato.ExtensivoDependente = list.extensivo_dependente;
                    configContrato.DescontoFolha = list.desconto_folha;

                    listConfigContrato.Add(configContrato);
                }

                return listConfigContrato;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public List<ConfiguracaoRegraContrato> SelectHistorico(int idBeneficio, int idContrato)
        {
            try
            {
                List<ConfiguracaoRegraContrato> listConfigConvencao = new List<ConfiguracaoRegraContrato>();

                var consulta = (from config in _context.tab_configuracao_regra_contrato
                                where config.tab_tipo_beneficio.id_tipo_beneficio == idBeneficio
                                && config.tab_contrato.Id_contrato == idContrato
                                orderby config.id_configuracao_regra_contrato descending
                                select new
                                {
                                    config.id_configuracao_regra_contrato,
                                    config.dt_inicio,
                                    config.dt_fim,
                                    config.tab_status.id_status,
                                    config.valor,
                                    config.obrigatorio,
                                    config.extensivo_dependente,
                                    config.desconto_folha
                                });

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    ConfiguracaoRegraContrato configContrato = new ConfiguracaoRegraContrato();
                    configContrato.IdConfiguracaoRegraContrato = list.id_configuracao_regra_contrato;
                    configContrato.DtInicio = list.dt_inicio;
                    configContrato.DtFim = list.dt_fim;
                    configContrato.Status = new Status(list.id_status);
                    configContrato.Valor = list.valor;
                    configContrato.Obrigatorio = list.obrigatorio;
                    configContrato.ExtensivoDependente = list.extensivo_dependente;
                    configContrato.DescontoFolha = list.desconto_folha;

                    listConfigConvencao.Add(configContrato);
                }

                return listConfigConvencao;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public DataTable SelectHistorico(int idBeneficio, int idContrato, bool carregaLocalidade)
        {
            try
            {
                DataTable gradeHistParam = new DataTable();

                EstruturaGradeHistParam(ref gradeHistParam);

                var consulta = (from config in _context.tab_configuracao_regra_contrato
                                where config.tab_tipo_beneficio.id_tipo_beneficio == idBeneficio
                                && config.tab_contrato.Id_contrato == idContrato
                                orderby config.id_configuracao_regra_contrato descending
                                select new
                                {
                                    config.id_configuracao_regra_contrato,
                                    config.dt_inicio,
                                    config.dt_fim,
                                    config.tab_status.id_status,
                                    config.valor
                                });

                var listConsulta = consulta.ToList();

                DataRow registro;
                foreach (var list in listConsulta)
                {
                    ConfiguracaoRegraContrato configContrato = new ConfiguracaoRegraContrato();
                    configContrato.IdConfiguracaoRegraContrato = list.id_configuracao_regra_contrato;
                    configContrato.DtInicio = list.dt_inicio;
                    configContrato.DtFim = list.dt_fim;
                    configContrato.Status = new Status(list.id_status);
                    configContrato.Valor = list.valor;

                    if (carregaLocalidade)
                        configContrato.Localidade = SelectLocalidadesConfig(list.id_configuracao_regra_contrato);

                    registro = gradeHistParam.NewRow();
                    if (configContrato.Localidade.Count > 0)
                    {
                        foreach (Cidade local in configContrato.Localidade)
                        {
                            registro["IdConfiguracaoRegraContrato"] = configContrato.IdConfiguracaoRegraContrato;
                            registro["DtInicio"] = configContrato.DtInicio;
                            registro["DtFim"] = configContrato.DtFim;
                            registro["Status"] = configContrato.Status.Descricao;
                            registro["Localidade"] = local.NomeCidade;
                        }
                    }
                    else
                    {
                        registro["IdConfiguracaoRegraConvencao"] = configContrato.IdConfiguracaoRegraContrato;
                        registro["DtInicio"] = configContrato.DtInicio;
                        registro["DtFim"] = configContrato.DtFim;
                        registro["Status"] = configContrato.Status.Descricao;
                    }

                    gradeHistParam.Rows.Add(registro);
                }

                return gradeHistParam;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #region Métodos de Persistência
        public void Salvar()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                try
                {
                    VerificarCadastro();

                    if (this._idConfiguracaoRegraContrato == 0)
                    {
                        tab_configuracao_regra_contrato tabConfiguracaoRegraContrato = new tab_configuracao_regra_contrato();

                        tabConfiguracaoRegraContrato.tab_contratoReference.EntityKey = new System.Data.EntityKey("GENTEEntities.tab_contrato", "Id_contrato", this._contrato.IdContrato);
                        tabConfiguracaoRegraContrato.tab_tipo_beneficioReference.EntityKey = new System.Data.EntityKey("GENTEEntities.tab_tipo_beneficio", "id_tipo_beneficio", this._beneficio.IdTipoBeneficio);
                        tabConfiguracaoRegraContrato.dt_inicio = this._dtInicio;
                        tabConfiguracaoRegraContrato.dt_fim = this._dtFim;
                        tabConfiguracaoRegraContrato.tab_statusReference.EntityKey = new System.Data.EntityKey("GENTEEntities.tab_status", "id_status", this._status.IdStatus);
                        tabConfiguracaoRegraContrato.valor = this._valor;
                        tabConfiguracaoRegraContrato.tab_tipo_valorReference.EntityKey = new System.Data.EntityKey("GENTEEntities.tab_tipo_valor", "id_tipo_valor", this._tipoValor.IdTipoValor);
                        tabConfiguracaoRegraContrato.obrigatorio = this._obrigatorio;
                        tabConfiguracaoRegraContrato.extensivo_dependente = this._extensivoDependente;
                        tabConfiguracaoRegraContrato.desconto_folha = this._descontoFolha;

                        _context.AddTotab_configuracao_regra_contrato(tabConfiguracaoRegraContrato);
                        _context.SaveChanges();

                        this._idConfiguracaoRegraContrato = RetornaIdConfiguracaoRegraContrato();

                        if (this._localidade != null)
                            SalvarLocalidade(this._idConfiguracaoRegraContrato);

                        DesativarConfiguracaoAnterior(this._idConfiguracaoRegraContrato, this._beneficio.IdTipoBeneficio);
                    }
                    else
                    {
                        tab_configuracao_regra_contrato tabConfiguracaoRegraContrato = (from config in _context.tab_configuracao_regra_contrato
                                                                                        where config.id_configuracao_regra_contrato == this._idConfiguracaoRegraContrato
                                                                                        select config).First();

                        tabConfiguracaoRegraContrato.tab_contratoReference.EntityKey = new System.Data.EntityKey("GENTEEntities.tab_contrato", "Id_contrato", this._contrato.IdContrato);
                        tabConfiguracaoRegraContrato.tab_tipo_beneficioReference.EntityKey = new System.Data.EntityKey("GENTEEntities.tab_tipo_beneficio", "id_tipo_beneficio", this._beneficio.IdTipoBeneficio);
                        tabConfiguracaoRegraContrato.dt_inicio = this._dtInicio;
                        tabConfiguracaoRegraContrato.dt_fim = this._dtFim;
                        tabConfiguracaoRegraContrato.tab_statusReference.EntityKey = new System.Data.EntityKey("GENTEEntities.tab_status", "id_status", this._status.IdStatus);
                        tabConfiguracaoRegraContrato.valor = this._valor;
                        tabConfiguracaoRegraContrato.tab_tipo_valorReference.EntityKey = new System.Data.EntityKey("GENTEEntities.tab_tipo_valor", "id_tipo_valor", this._tipoValor.IdTipoValor);
                        tabConfiguracaoRegraContrato.obrigatorio = this._obrigatorio;
                        tabConfiguracaoRegraContrato.extensivo_dependente = this._extensivoDependente;
                        tabConfiguracaoRegraContrato.desconto_folha = this._descontoFolha;

                        _context.SaveChanges();
                    }

                    scope.Complete();
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        }
        #endregion

        #endregion
    }
}
